package com.atguigu.yygh.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.consts.MqConst;
import com.atguigu.yygh.enums.*;
import com.atguigu.yygh.exception.YyghException;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.order.PaymentInfo;
import com.atguigu.yygh.model.order.RefundInfo;
import com.atguigu.yygh.order.prop.WeixinPayProp;
import com.atguigu.yygh.order.service.OrderInfoService;
import com.atguigu.yygh.order.service.PaymentInfoService;
import com.atguigu.yygh.order.service.RefundInfoService;
import com.atguigu.yygh.order.service.WeixinService;
import com.atguigu.yygh.order.utils.HttpClient;
import com.atguigu.yygh.order.utils.HttpRequestHelper;
import com.atguigu.yygh.serice.RabbitService;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author A
 * @version 1.0
 * @description: TODO
 * @date 2025/4/1 1:32
 */
@Service
public class WeixinServiceImpl implements WeixinService {
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private PaymentInfoService paymentInfoService;
    @Autowired
    private WeixinPayProp weixinPayProp;
    @Autowired
    private RefundInfoService refundInfoService;
    @Autowired
    private RabbitService rabbitService;
    @Override
    public String createNative(Long orderId) {
        //根据订单号查询订单信息
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        // 保存交易记录
        paymentInfoService.savePaymentInfo(orderInfo, PaymentTypeEnum.WEIXIN.getStatus());
        // 调用微信支付接口生成二维码
        //1、设置参数
        Map paramMap = new HashMap();
        paramMap.put("appid", weixinPayProp.getAppid());
        paramMap.put("mch_id", weixinPayProp.getPartner());
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        Date reserveDate = orderInfo.getReserveDate();
        String reserveDateString = new DateTime(reserveDate).toString("yyyy/MM/dd");
        String body = reserveDateString + "就诊" + orderInfo.getDepname();
        paramMap.put("body", body);
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo());
        //paramMap.put("total_fee", order.getAmount().multiply(new BigDecimal("100")).longValue()+"");
        paramMap.put("total_fee", "1");//为了测试
        paramMap.put("spbill_create_ip", "127.0.0.1");
        paramMap.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify");
        paramMap.put("trade_type", "NATIVE");
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
        //2、发送请求
        try {
            httpClient.setXmlParam(WXPayUtil.generateSignedXml(paramMap, weixinPayProp.getPartnerkey()));
            httpClient.setHttps(true);
            httpClient.post();
            // 返回二维码地址
            String xml = httpClient.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(xml);
            // 二维码地址
            return map.get("code_url");
        } catch (Exception e) {
            throw new RuntimeException("微信支付接口调用失败");
        }

    }

    @Override
    public Map<String, String> queryPayStatus(Long orderId) {
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        //1、封装参数
        Map paramMap = new HashMap<>();
        paramMap.put("appid", weixinPayProp.getAppid());
        paramMap.put("mch_id", weixinPayProp.getPartner());
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo());
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        //2、设置请求
        try {
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, weixinPayProp.getPartnerkey()));
            client.setHttps(true);
            client.post();
            //3、解析结果
            String xml = client.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(xml);
            return map;
        } catch (Exception e) {
            return null;
        }


    }

    @Override
    public Boolean cancelOrder(Long orderId) {
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        //当前时间大余退号时间，不能取消预约
        if (new DateTime(orderInfo.getQuitTime()).isBeforeNow()) {
            throw new YyghException(20001, "预约时间已过，不能取消预约");
        }
        //1、封装参数
        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("hoscode", orderInfo.getHoscode());
        reqMap.put("hosRecordId", orderInfo.getHosRecordId());
        reqMap.put("timestamp", HttpRequestHelper.getTimestamp());
        reqMap.put("sign", "");
        //2、给医院平台发送请求
        JSONObject jsonObject = HttpRequestHelper.sendRequest(reqMap, "http://localhost:9998/order/updateCancelStatus");
        if (jsonObject.getInteger("code") != 200) {
            throw new YyghException(ResultEnum.ERROR.getCode(), jsonObject.getString("message"));

        } else {
            //判断是否已经支付
            if (Objects.equals(orderInfo.getOrderStatus(), OrderStatusEnum.PAID.getStatus())) {
                //已经支付，退款
                Boolean isRefund = refund(orderId);
                if (!isRefund){
                    throw new YyghException(20001, "退款失败");
                }
            }
            //更改订单状态
            orderInfo.setOrderStatus(OrderStatusEnum.CANCLE.getStatus());
            orderInfoService.updateById(orderInfo);
            //更改支付记录状态
            paymentInfoService.updatePaymentInfoStatusByOrderId(orderId, PaymentStatusEnum.REFUND.getStatus());
            //发送mq信息更新预约数 我们与下单成功更新预约数使用相同的mq信息，不设置可预约数与剩余预约数，接收端可预约数减1即可
            OrderMqVo orderMqVo = new OrderMqVo();
            orderMqVo.setScheduleId(orderInfo.getScheduleId());
            MsmVo msmVo = new MsmVo();
            msmVo.setPhone("18289646811:退款");
            orderMqVo.setMsmVo(msmVo);
            rabbitService.sendMesssage(MqConst.EXCHANGE_DIRECT_ORDER, MqConst.ROUTING_ORDER, orderMqVo);

        }
        return true;
    }

    private Boolean refund(Long orderId) {
        //先查询支付记录
        PaymentInfo paymentInfo = paymentInfoService.findByOrderId(orderId);
        //更新退款记录并返回
        RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfo);
        //判断是否已经退款
        if (Objects.equals(refundInfo.getRefundStatus(), RefundStatusEnum.REFUND.getStatus())) {
            return true;
        }
        //未退款，调用微信退款接口
        //1、封装参数
        Map<String, String> paramMap = new HashMap<>(8);
        paramMap.put("appid", weixinPayProp.getAppid());       //公众账号ID
        paramMap.put("mch_id", weixinPayProp.getPartner());   //商户编号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        paramMap.put("transaction_id", paymentInfo.getTradeNo()); //微信订单号
        paramMap.put("out_trade_no", paymentInfo.getOutTradeNo()); //商户订单编号
        paramMap.put("out_refund_no", "tk" + paymentInfo.getOutTradeNo()); //商户退款单号
        //       paramMap.put("total_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
        //       paramMap.put("refund_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
        paramMap.put("total_fee", "1");
        paramMap.put("refund_fee", "1");
        try {
            String paramMapXml = WXPayUtil.generateSignedXml(paramMap, weixinPayProp.getPartnerkey());
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
            httpClient.setXmlParam(paramMapXml);
            httpClient.setHttps(true);
            httpClient.setCert(true);
            httpClient.setCertPassword(weixinPayProp.getPartner());
            httpClient.post();
            //3、解析结果
            String xml = httpClient.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(xml);
            if (null !=map && WXPayConstants.SUCCESS.equalsIgnoreCase(map.get("return_code"))) {
                //退款成功，更新支付记录
                refundInfo.setCallbackTime(new Date());
                refundInfo.setTradeNo(map.get("refund_id"));
                refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());
                refundInfo.setCallbackContent(JSONObject.toJSONString(map));
                refundInfoService.updateById(refundInfo);
                return true;
            }
            //退款失败，更新支付记录
            return false;
        } catch (Exception e) {
            e.printStackTrace();

        }
        return false;
    }
}
